//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<lock.cpp>
///	@path	~/src/lib/system/
///	@date	2007/10/24
///	@desc	Lock implementation.

#include "config/config.h"

#include "lib/system/lock.h"

namespace xeres {

	// ctor
	GlobalLock::GlobalLock( const WString& name , bool open_exist )
	{
		if( open_exist )
		{
			assert( !name.empty() );
			m_lockImpl = (void*) ::OpenMutex( MUTEX_MODIFY_STATE , FALSE , name.c_str() );
			if( m_lockImpl == NULL )
			{
				__win32_error( _S("GlobalLock::CTOR: Failed to open mutex object: %s.") );
				FATAL_ABORT( _S("Mutex open") );
			}
		}
		else
		{
			m_lockImpl = (void*) ::CreateMutex( NULL , FALSE , name.empty() ? NULL : name.c_str() );
			if( m_lockImpl == NULL )
			{
				__win32_error( _S("GlobalLock::CTOR: Failed to create mutex object: %s.") );
				FATAL_ABORT( _S("Mutex creation") );
			}
		}
	}

	// duplicate mutex
	GlobalLock::GlobalLock( const GlobalLock& rhs )
	{
		HANDLE hProcess = ::GetCurrentProcess();
		HANDLE hMutex = NULL;
		if( ::DuplicateHandle(
			hProcess ,
			(HANDLE)rhs.m_lockImpl ,
			hProcess ,
			&hMutex ,
			0 ,
			FALSE ,
			DUPLICATE_SAME_ACCESS ) == FALSE )
		{
			__win32_error( _S("GlobalLock::CTOR: Failed to duplicate event object: %s.") );
			FATAL_ABORT( _S("Mutex duplication") );
		}
		m_lockImpl = (void*)hMutex;
	}

	// dtor
	GlobalLock::~GlobalLock( void )
	{
		if( ::CloseHandle( (HANDLE)m_lockImpl ) == FALSE )
		{
			__win32_error( _S("GlobalLock::DTOR: Failed to close mutex handle: %s.") );
		}
	}

	// acquire lock
	void GlobalLock::Acquire( void )
	{
		::WaitForSingleObject( (HANDLE)m_lockImpl , INFINITE );
	}

	// release lock
	void GlobalLock::Release( void )
	{
		::ReleaseMutex( (HANDLE)m_lockImpl );
	}

	// try acquire lock
	bool GlobalLock::TryAcquire( const Time& wait )
	{
		return ( ::WaitForSingleObject( (HANDLE)m_lockImpl , (DWORD)wait.ToMilliSecond() ) == WAIT_OBJECT_0 );
	}

	bool GlobalLock::TryAcquire( void )
	{
		return ( ::WaitForSingleObject( (HANDLE)m_lockImpl , 0 ) == WAIT_OBJECT_0 );
	}

} // namespace xeres
